using System;

namespace MyUtils
{
	/// <summary>
	/// Design pattern for the base class.
	/// By implementing IDisposable, you are announcing that instances
	/// of this type allocate scarce resources.
	/// Inheriting CriticalFinalizingObject make JIT compile of finalizers on object creation, and ensures, that no errors will occur and finalizers really will executed, even if there are no memory for JIT compiling
	/// </summary>
	public abstract class Disposable :
#if !PocketPC
		System.Runtime.ConstrainedExecution.CriticalFinalizerObject,
#endif
		IDisposable
	{
		/// <summary>
		/// Track whether Dispose has been called.
		/// </summary>
		bool _isDisposed, _isDisposing;

		/// <summary>
		/// Provide way to check, if object are disposed.
		/// </summary>
		public bool IsDisposed
		{
			get { return _isDisposed; }
		}
	
		/// <summary>
		/// Provide way to check, if disposing is started.
		/// </summary>
		public bool IsDisposing
		{
			get { return _isDisposing; }
		}

		/// <summary>
		/// Implement IDisposable.
		/// A derived class should not be able to override this method.
		/// </summary>
		public void Dispose()
		{
			Dispose(true);

			// Take yourself off the Finalization queue 
			// to prevent finalization code for this object
			// from executing a second time.
			GC.SuppressFinalize(this);
		}

		// Dispose(bool disposing) executes in two distinct scenarios.
		/// <summary>
		/// </summary>
		/// <param name="disposeManaged">
		/// If disposing equals true, the method has been called directly
		/// or indirectly by a user's code. Managed and unmanaged resources
		/// can be disposed.
		/// If disposing equals false, the method has been called by the 
		/// runtime from inside the finalizer and you should not reference 
		/// other objects. Only unmanaged resources can be disposed.
		/// </param>
		// NOTE: This is not protected virtual, because it is end solution for disposing derived classes. Use override of DisposingManaged and DisposingUnmanaged for provide disposing code.
		void Dispose(bool disposeManaged)
		{
			// Check to see if Dispose has already been called.
			if (_isDisposing)
			{
				return;
			}
			_isDisposing = true;
			if (disposeManaged)
			{
				DisposeManaged();
			}
			DisposeUnmanaged();
			_isDisposed = true;
		}

		/// <summary>
		/// Method for disposing large managed resource
		/// </summary>
		protected virtual void DisposeManaged() {}

		/// <summary>
		/// Method for disposing unmanaged resource
		/// Remember: do not throw an exception (will skipped), do not use managed members (can be already disposed), do not create infinity loop (locking of finalizing thread, and create memory leak), and make as can as possible small code (for excellent performance, because code is executed for all objects of this type). Note, that object can be unstable in case a constructor throws exception (a destructor will be called).
		/// </summary>
		protected virtual void DisposeUnmanaged() {}

		/// <summary>
		/// In code of derrived classes you can check, is this instance is disposed. If it is a true, an exception will throw
		/// </summary>
		protected void CheckAndThrowIfDisposed()
		{
			if (_isDisposed)
			{
				throw new ObjectDisposedException(ToString());
			}
		}

		// Use C# destructor syntax for finalization code.
		// This destructor will run only if the Dispose method 
		// does not get called.
		// It gives your base class the opportunity to finalize.
		// Do not provide destructors in types derived from this class.
		~Disposable()
		{
			// Do not re-create Dispose clean-up code here.
			// Calling Dispose(false) is optimal in terms of
			// readability and maintainability.
			Dispose(false);
		}

		/// <summary>
		/// Determined destruct of object and releasing scared and managed resources.
		/// Do not make this method virtual. A derived class should not be allowed to override this method.
		/// </summary>
		public void Close()
		{
			Dispose();
		}
	}
}